﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevComponents.DotNetBar;
using System.IO;
using Matrix_ClassLibrary;

namespace LTTT_server
{
    public partial class FormSender :DevComponents.DotNetBar.Office2007RibbonForm
    {
        ConnectionServer connect; // đối tượng lớp connect server
        Matrix matrix; // ma trận sinh bên server
        int DistanceHamming = 0;
        static internal bool Sent = false;
        static internal Matrix newmatrix = null;

        public FormSender()
        {
            InitializeComponent();
            tbU.Enabled = false;
        }

        private void buttonX1_Click(object sender, EventArgs e)
        {

        }
        // sự kiện Mở ma trận từ file
        private void buttonItem3_Click(object sender, EventArgs e)
        {
            OpenFileDialog fd = new OpenFileDialog();
            if (fd.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    //MessageBox.Show(fd.FileName);
                    // Tạo đối tượng ma trận từ contructor lấy dữ liệu tư file
                    matrix = new Matrix(fd.FileName, true);
                    // Xác định khoảng cách hamming
                    DistanceHamming = matrix.DistanceHamming;
                    labelHamming.Text = "Khoảng cách hamming của bộ mã: " + DistanceHamming.ToString();
                    ResetTextbox();
                    tbU.MaxLength = matrix.row; //gán chiều dài lớn nhất cho textbox nhập U
                    tbNoise.MaxLength = matrix.column; //gán chiều dài lớn nhất cho textbox nhập nhiễu
                    //nếu tồn tại dữ liệu trong datagrid view thì sẽ xóa hết
                    if (dgvMatrix.RowCount > 1)
                    {
                        dgvMatrix.RowCount = 1;
                        dgvMatrix.Rows.Clear();
                        dgvMatrix.Columns.Clear();
                        Sent = false;
                    }
                    SetupDataGridView(matrix);
                }
                catch
                {
                    MessageBox.Show("File không hợp lệ!","Sender: Lỗi",MessageBoxButtons.OK,MessageBoxIcon.Error);
                }
            }
        }
        
        // Reset lại các textbox
        private void ResetTextbox()
        {
            tbNoise.Text = "";
            tbU.Text = "";
        }

        // Cài đặt hiển thị cho Datagridview
        private void SetupDataGridView(Matrix matrix)
        {
            DataGridViewTextBoxColumn boxcolumn;
            DataGridViewCellStyle cellStyle;
            this.Controls.Add(dgvMatrix);
            DataGridViewCellStyle style =
                dgvMatrix.ColumnHeadersDefaultCellStyle;
            style.BackColor = Color.White;
            style.ForeColor = Color.White;
            style.Font = new Font(dgvMatrix.Font, FontStyle.Bold);
            dgvMatrix.EditMode = DataGridViewEditMode.EditOnEnter;
            dgvMatrix.Name = "dgvMatrix";
            dgvMatrix.AutoSizeRowsMode =
                DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders;
            dgvMatrix.ColumnHeadersBorderStyle =
                DataGridViewHeaderBorderStyle.Raised;
            dgvMatrix.CellBorderStyle = DataGridViewCellBorderStyle.Single;
            dgvMatrix.GridColor = SystemColors.ActiveBorder;
            dgvMatrix.RowHeadersVisible = false;


            for (int i = 0; i < matrix.column; i++)
            {
                boxcolumn = new DataGridViewTextBoxColumn();
                cellStyle = new DataGridViewCellStyle();
                if (i % 2 == 1)
                {
                    cellStyle.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
                    boxcolumn.DefaultCellStyle = cellStyle;

                }
                boxcolumn.HeaderText = "a" + (i + 1).ToString();
                boxcolumn.Width = dgvMatrix.Width / matrix.column;
                dgvMatrix.Columns.Add(boxcolumn);

            }
            //Bỏ chức năng sort column của datagridview
            foreach (DataGridViewColumn col in dgvMatrix.Columns)
            {
                col.SortMode = DataGridViewColumnSortMode.NotSortable;
            }
            // thêm từng dòng vào datagridview
            string[] arrInt = new string[matrix.column];
            for (int i = 0; i < matrix.row; i++)
            {
                //gán giá trị của từng dòng
                for (int j = 0; j < matrix.column; j++)
                    arrInt[j] = matrix.element[i, j].ToString();
                //add giá trị từng dòng vào datagridview
                this.dgvMatrix.Rows.Add(arrInt);
            }
            tbU.Enabled = true;
        }

        // Start Server
        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                // tạo một đối tượng lớp connect
                connect = new ConnectionServer(tbIP.Text);
                connect.StartServer(); // start server
                // Gán kết sự kiện xử lý sau khi nhận lại thông điệp từ client
                connect.ProcessAfterReceiveMessage += new ConnectionServer.DoSomeThingMethod(OnReceiveMessage);
                tbIP.Enabled = false;
                btnSendMatrix.Enabled = true;
                btnStart.Enabled = false;
                btnStop.Enabled = true;
            }
            catch (ArgumentNullException arg)
            {
                MessageBox.Show(arg.Message);
            }
        }

        // Gửi thông điệp cho receiver
        private void btnSend_Click(object sender, EventArgs e)
        {
            string thongbao;
            if (Sent)
            {
                if (chkRandomNoise.Checked == true) AutoMakeNoise();
                if (!KiemTraSoKiTu_U(tbU.Text, out thongbao))
                {
                    MessageBox.Show(thongbao, "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
                if (!KiemTraSoKiTu_Noise(tbNoise.Text, out thongbao))
                {
                    MessageBox.Show(thongbao, "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }
                // Kiem tra xem gửi có nhiễu không.
                if (tbU.Text != "" && tbNoise.Text != "")
                {
                    try
                    {
                      
                    Matrix a = new Matrix(tbU.Text); // tạo ma trận từ thông báo muốn gửi
                    Matrix v = a.Multiply(matrix); // nhân thông báo với ma trận sinh tạo ra từ mã
                    Matrix b = new Matrix(tbNoise.Text); // tạo ma trận đơn dòng cho nhiễu
                    connect.SendMessage(v.Addition(b).ToString()); // cộng từ mã với nhiễu và gửi cho server.
                    } 
                    catch (ArgumentException ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
                else if (tbU.Text != "" && tbNoise.Text == "")
                {
                    // Gửi thông điệp U đi
                    connect.SendMessage(new Matrix(tbU.Text).Multiply(matrix).ToString());
                }
            }
            else
            {
                MessageBox.Show("Bạn chưa gửi ma trận hiện tại qua cho client", "Sender: Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private bool KiemTraSoKiTu_U(string txt, out string thongbao)
        {
            if (txt.Length == 0)
            {
                thongbao = "Bạn chưa nhập thông điệp";
                return false;
            }
            if (txt.Length < matrix.row)
            {
                thongbao = "Thông điệp của bạn chưa đủ dài!";
                return false;
            }

            thongbao = "";
            return true;
        }

        private bool KiemTraSoKiTu_Noise(string txt, out string thongbao)
        {

            if (txt.Length < matrix.column && txt.Length != 0)
            {
                thongbao = "Nhiễu của bạn chưa đủ dài!";
                return false;
            }

            thongbao = "";
            return true;
        }

        public void OnReceiveMessage(string message)
        {
            if (connect.ReceiveMessages == "1")
            {
                MessageBox.Show("Client yêu cầu gửi lại từ mã","Thông báo :",MessageBoxButtons.OK,MessageBoxIcon.Information);
            }
        }

        //Tự động tạo nhiễu trong khoảng phát hiện được
        private void AutoMakeNoise()
        {
            if (matrix == null)
            {
                MessageBox.Show("Ma trận sinh không tồn tại");
                return;
            }
           // Matrix TestingMT = matrix.MakeTestingMatrix();


            if (chkRandomNoise.Checked == true)
            {
               // d = XacDinhKCHamming(TestingMT);
                if (DistanceHamming == -1) MessageBox.Show("Ma trận sinh nhập vào không hợp lệ", "Sender: Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error);
                else if (DistanceHamming < 2) MessageBox.Show("Với ma trận sinh đã cho, không thể tạo được nhiễu", "Sender: Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
                else
                {
                    tbNoise.Text = MakeNoise(DistanceHamming);
                }
            }
        }

        //Kiểm tra tổng của 1 cột có = 0, nếu có trả về true, nếu không trả về false
        private bool CheckSumIsZero(int[] a)
        {
            int sum = 0;
            for (int x = 0; x < (matrix.column - matrix.row); x++)
                sum += a[x];
            if (sum % 2 == 0) return true;
            else return false;
        }


        //Tạo nhiễu với khoảng cách hamming d cho trước
        private string MakeNoise(int d)
        {
            int MaxSai = d;
            Random rand = new Random();
            int rd = rand.Next(0, MaxSai);

            int[] array = new int[matrix.column];

            for (int i = 0; i < matrix.column; i++)
            {
                array[i] = 0;
            }

            for (int i = 0; i < rd; i++)
            {
                Random rand2 = new Random();
                int rd2 = rand2.Next(0, matrix.column);
                if (array[rd2] != 1) array[rd2] = 1;
                else i--;
            }


            var builder = new StringBuilder();
            Array.ForEach(array, x => builder.Append(x));
            var res = builder.ToString();
            return res;
        }

        private void btnSendMatrix_Click(object sender, EventArgs e)
        {
            if (dgvMatrix.RowCount > 0)
            {
                //Lấy ma trận từ datagridview để gửi cho client
                GenerateMatrixFromDataGridView();

                //Kiểm tra tính hợp lệ của ma trận sinh
                if (matrix.column > Math.Pow(2, matrix.column - matrix.row) - 1)
                {
                    MessageBox.Show("Ma trận không hợp lệ!", "Sender: Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                // Kiểm tra xem ma trận có thể tạo ra ma trận sinh được không
                try
                {
                    Matrix TestingMatrix = matrix.MakeTestingMatrix();
                    if (matrix.testingMatrixColumnPosition.Keys.Count < matrix.column)
                    {
                        MessageBox.Show("Ma trận kiểm tra của ma trận sinh này có cột bị trùng \n Không thể sử dụng để sửa lỗi ở client", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        //làm disable nhiễu.
                        if (matrix.DistanceHamming <= 1)
                        {
                            chkRandomNoise.Checked = false;
                            chkRandomNoise.Enabled = false;
                            tbNoise.Enabled = false;
                        }
                    }
                    else // reset lại các texbox
                    {
                        //làm disable nhiễu.
                        chkRandomNoise.Checked = false;
                        chkRandomNoise.Enabled = true;
                        tbNoise.Enabled = true;
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                // Nếu được tiến hành gửi ma trận
                try
                {
                    connect.SendMatrix(matrix);
                }
                catch
                {
                    MessageBox.Show("Không thể gửi được ma trận cho client!", "Sender: Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                Sent = true;
            }
            else
            {
                MessageBox.Show("Chưa có ma trận!", "Sender: Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }
        // Nhưng Server;
        private void btnStop_Click(object sender, EventArgs e)
        {
            try
            {
                connect.StopServer();
                btnSendMatrix.Enabled = false;
                btnStart.Enabled = true;
                btnStop.Enabled = false;
            }
            catch
            {
                return;
            }
        }
        // Checkbox nhiễu tự động thay đổi
        private void chkRandomNoise_CheckedChanged(object sender, EventArgs e)
        {
            if (chkRandomNoise.Checked)
            {
                tbNoise.Text = "";
                tbNoise.Enabled = false;
            }
            else
            {
                tbNoise.Text = "";
                tbNoise.Enabled = true;
            }
        }
        // Sự kiện nhập thông điệp U
        private void tbU_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!Char.IsControl(e.KeyChar) && e.KeyChar != '1' && e.KeyChar != '0')
                e.Handled = true;
        }
        // Sự kiện nhập nhiễu
        private void tbNoise_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!Char.IsControl(e.KeyChar) && e.KeyChar != '1' && e.KeyChar != '0')
                e.Handled = true;
        }
        // sự kiển nhập nhiễu cho datagridview
        private void dgvMatrix_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            dgvMatrix.Rows[e.RowIndex].ErrorText = "";
            if (dgvMatrix.Rows[e.RowIndex].IsNewRow) { return; }
            if (e.FormattedValue.ToString() != "0" && e.FormattedValue.ToString() != "1" )
            {
                e.Cancel = true;
                MessageBox.Show("số nhập phải là 0 hoặc 1");
            }
        }
       
        //Lưu ma trận
      private void buttonItem4_Click(object sender, EventArgs e)
        {
            if (dgvMatrix.IsCurrentCellInEditMode) dgvMatrix.EndEdit();
            SaveFileDialog savedialog = new SaveFileDialog();
            savedialog.Filter = "Text file|*.txt";
            savedialog.Title = "Lưu lại ma trận sinh";
            savedialog.ShowDialog();

            if (savedialog.FileName != "")
            {
                FileStream file = File.Create(savedialog.FileName);
                StreamWriter writer = new StreamWriter(file);
                
                if (dgvMatrix.Rows.Count > 0)
                {
                    for (int i = 0; i < dgvMatrix.Rows.Count; i++)
                    {
                        string line = "";
                        for (int j = 0; j < dgvMatrix.Columns.Count; j++)
                        {
                            if (j != dgvMatrix.Columns.Count - 1)
                            {
                                line += dgvMatrix.Rows[i].Cells[j].Value.ToString() + " ";
                            }
                            else
                            {
                                line += dgvMatrix.Rows[i].Cells[j].Value.ToString();
                            }
                        }
                        writer.WriteLine(line);
                    }
                }
                else
                {
                    MessageBox.Show("Chưa có ma trận!");
                }

                writer.Close();
                file.Close();
            }
        }

        private void FormSender_Load(object sender, EventArgs e)
        {
            //không cho người dùng phóng to cửa sổ
            MaximizeBox = false;
            // gắn ràng buộc sự kiển nhập cho datagridview
            dgvMatrix.CellValidating += new DataGridViewCellValidatingEventHandler(dgvMatrix_CellValidating);
        }

        private void buttonItem13_Click(object sender, EventArgs e)
        {
            //Thoát chương trình
            Application.Exit();
        }

        //Tạo ma trận 3x6
        private void btnMatrix36_Click(object sender, EventArgs e)
        {
            if (dgvMatrix.Rows.Count > 0)
            {
                dgvMatrix.Rows.Clear();
                dgvMatrix.Columns.Clear();
            }
            Matrix matrix36 = new Matrix(3, 6);
            SetupDataGridView(matrix36);
            Sent = false;
        }

        //Hàm tạo ma trận từ datagridview
        private void GenerateMatrixFromDataGridView()
        {
            
            matrix = new Matrix(dgvMatrix.Rows.Count, dgvMatrix.Columns.Count);
            for (int i=0;i<dgvMatrix.Rows.Count;i++)
                for (int j = 0; j < dgvMatrix.Columns.Count; j++)
                {
         
                    matrix.element[i,j] = System.Convert.ToInt32(dgvMatrix.Rows[i].Cells[j].Value);
                }
            // Xác định khoảng cách hamming
            DistanceHamming = matrix.DistanceHamming;
            labelHamming.Text = "Khoảng cách hamming của bộ mã: " + DistanceHamming.ToString();
            // gắn sự kiện nhập cho U và nhiễu
            tbU.MaxLength = matrix.row; //gán chiều dài lớn nhất cho textbox nhập U
            tbNoise.MaxLength = matrix.column; //gán chiều dài lớn nhất cho textbox nhập nhiễu
        }

        // ràng buộc sự kiện nhập cho datagridview
        
        //Tạo ma trận 4x7
        private void btnMatrix47_Click(object sender, EventArgs e)
        {
            if (dgvMatrix.Rows.Count > 0)
            {
                dgvMatrix.Rows.Clear();
                dgvMatrix.Columns.Clear();
            }
            Matrix matrix47=new Matrix(4,7);
            SetupDataGridView(matrix47);
            Sent = false;
        }

        //Tạo ma trận 4x8
        private void btnMatrix48_Click(object sender, EventArgs e)
        {
            if (dgvMatrix.Rows.Count > 0)
            {
                dgvMatrix.Rows.Clear();
                dgvMatrix.Columns.Clear();
            }
            Matrix matrix48 = new Matrix(4, 8);
            SetupDataGridView(matrix48);
            Sent = false;
        }

        //Tạo ma trận tùy ý
        private void btnOption_Click(object sender, EventArgs e)
        {
            NewMatrix frmNewMatrix = new NewMatrix();
            DialogResult dlg=frmNewMatrix.ShowDialog();
            if (dlg == DialogResult.OK)
            {
                if (dgvMatrix.Rows.Count > 0)
                {
                    dgvMatrix.Rows.Clear();
                    dgvMatrix.Columns.Clear();
                }
                SetupDataGridView(newmatrix);
            }
        }


    }
}